﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	WebListService.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using Microsoft.SharePoint;

namespace Smart.Common.Entities
{
	public class WebListService<TEntityType> : ListService<TEntityType>
		where TEntityType : Entity
	{
		private SPList _list;

		/// <summary>
		/// SharePoint List (lazy field)
		/// </summary>
		public SPList List
		{
			get { return _list ?? (_list = (SPList)Ctx.GetSource(Meta)); }
			set { _list = value; }
		}

		/// <summary>
		/// Server object model list service
		/// </summary>
		public WebListService(IEntityScope ctx, string listName, IEntityMapper mapper, MetaList meta)
			: base(ctx, listName, mapper, meta)
		{
			//List = (SPList)Ctx.GetSource(Meta);
		}

		/// <summary>
		/// Server object model list service
		/// </summary>
		public WebListService(SPList list, IEntityMapper mapper, MetaList meta)
			: base(null, list.GetUrl(), mapper, meta)
		{
			List = list;
		}

		public override EntityInfo DetectEntityInfo(object item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			var spi = item as SPListItem;

			if (spi != null)
			{
				var ctid = spi.ContentTypeId;

				var ei = EntityFactory.QueryEntityByContentType(ctid.ToString());

				if (ei != null)
					return ei;

				ei = EntityFactory.QueryEntityByContentType(ctid.Parent.ToString());

				if (ei != null)
					return ei;

				var contentType = spi.ContentType != null ? spi.ContentType.Name : null;

				if (contentType.IsNullOrEmpty())
					return EntityFactory.QueryEntity(DefaultEntityType);

				return
					EntityFactory.QueryEntityByContentType(contentType) ?? EntityFactory.QueryEntity(DefaultEntityType);
			}

			var row = item as DataRowView;

			if (row != null)
			{
				try
				{
					if (row.DataView.Table.Columns.Contains("ContentTypeId"))
					{
						var ctid = new SPContentTypeId(row["ContentTypeId"].SToStr());

						var ei = EntityFactory.QueryEntityByContentType(ctid.ToString());

						if (ei != null)
							return ei;

						ei = EntityFactory.QueryEntityByContentType(ctid.Parent.ToString());

						if (ei != null)
							return ei;
					}
				}
				catch
				{
				}

				try
				{
					if (row.DataView.Table.Columns.Contains("ContentType"))
					{
						var contentType = row["ContentType"].SToStr();

						if (contentType.IsNullOrEmpty())
							return EntityFactory.QueryEntity(DefaultEntityType);

						var ei = EntityFactory.QueryEntityByContentType(contentType);

						if (ei != null)
							return ei;
					}
				}
				catch
				{
				}

				return EntityFactory.QueryEntity(DefaultEntityType);
			}

			throw new NotSupportedException();
		}

		protected override Identifier GetId(object item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			return ((SPListItem)item).ID;
		}

		protected override object CreateItem()
		{
			if (List == null)
				throw new NotSupportedException();

			return List.AddItem();
		}

		protected override object LoadItem(Identifier id)
		{
			if (id.IsEmpty)
				throw new ArgumentException("id");

			if (List == null)
				throw new NotSupportedException();

			return List.GetItemById(id.Int);
		}

		protected override bool SaveItem(Identifier id, object item, bool isNew)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			var spi = (SPListItem)item;

			bool res;

			try
			{
				spi.Update();

				res = true;
			}
			catch (Exception x)
			{
				H.LX("SaveItem", x);

				res = false;
			}

			return res;
		}

		protected override bool RecycleItem(Identifier id)
		{
			if (id.IsEmpty)
				throw new ArgumentException("id");

			var res = false;

			try
			{
				if (List == null)
					throw new NotSupportedException();

				var item = List.GetItemById(id.Int);

				if (item != null)
				{
					res = !item.Recycle().IsEmpty();
				}
			}
			catch (Exception x)
			{
				H.LX("RecycleItem.1", x);

				res = false;
			}

			return res;
		}

		protected override bool RecycleItem(object item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			bool res;

			try
			{
				res = !((SPListItem)item).Recycle().IsEmpty();
			}
			catch (Exception x)
			{
				H.LX("RecycleItem.2", x);

				res = false;
			}

			return res;
		}

		protected override IEnumerable LoadItems(string query, int rowLimit, Dictionary<string, object> properties)
		{
			return SPH.GetFilteredItems(List, query, (uint)rowLimit, properties);
		}
	}
}